/*
* commentsmodel.h - This file is the part of the wp-notifier.(code name "luan luan")
* Copyright (C) 2010 Dean Lee <deanlee3@gmail.com>, http://www.deanlee.cn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
* Acknowledgements:
*   <> Many thanks to all of you, who have encouraged me to update my articles
*     and code, and who sent in bug reports and fixes.
* 
*/
#ifndef COMMENTSMODEL_H
#define COMMENTSMODEL_H
#include <QAbstractListModel>
#include <QSortFilterProxyModel>
#include <QTextDocument>
#include "wpxmlrpc.h"
#include "blog.h"
class CommentsModel : public QAbstractListModel
{
	Q_OBJECT
public:
	class CommentItem
	{
	public:
		CommentItem(const Comment& c) : comment(c)
		{
			doc.setUndoRedoEnabled(false);
			doc.setDocumentMargin(0);
			doc.setHtml(c.content());
			
		}
		~CommentItem()
		{
		}
		Comment comment;
		QRect rcAuthor;
		QRect rcPostTitle;
		QTextDocument doc;
	};

	enum Roles{datetimeRole = Qt::UserRole + 1, commentStatusRole, commentPointerRole, unreadRole};

	CommentsModel(QObject * parent = 0);
	~CommentsModel();
	void setBlog(const Blog& blog);
	void fromXml(const QDomElement& el);
	QDomElement toXml(QDomDocument *doc)const;


	Blog blog()const{return m_blog;}
	int approved()const{return m_commentOffset[CommentData::approve].m_count;}
	int spam()const{return m_commentOffset[CommentData::spam].m_count;}
	int hold()const{return m_commentOffset[CommentData::hold].m_count;}
	void editComment(const QModelIndex& index, const QString& status, const QString& content);
	void deleteComment(const QModelIndex& index);
	void replyComment(const QModelIndex& index, const QString& content);
	void setComments(const QList<Comment>& comments);
	QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex()) const ;
	int rowCount(const QModelIndex &parent = QModelIndex()) const;
	QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
	bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
	Qt::ItemFlags flags ( const QModelIndex & index) const;
	bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex());
	//void fetchMore(const QModelIndex & parent);
	//bool canFetchMore(const QModelIndex & parent) const;
	void fetchMore(CommentData::CommentStatus status);
	void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
	static bool itemGreaterThan(const QPair<CommentItem*,int> &left,
		const QPair<CommentItem*, int> &right);
	static bool itemLessThan(const QPair<CommentItem*,int> &left,
		const QPair<CommentItem*, int> &right);

	bool canFetchMore(CommentData::CommentStatus status) const;
signals:
	void hasNewComments(int approved, int hold, int spam);
	void commentsCountChanged();
	void refreshFinished();
public slots:
	void refresh();

protected slots:
	void xmlrpcFinished(bool);
	//void commentsRefreshed();
protected:
	class CommentPrivateData
	{
	public:
		CommentPrivateData(){m_bCanFetch = false;m_offset = m_newComments = m_count = 0;}
		~CommentPrivateData(){}
		int m_offset;
		int m_count;
		int m_newComments;
		bool m_bCanFetch;
	};
	CommentPrivateData m_commentOffset[3];
	int m_nLastId;
	int m_refreshCount;
	QList<CommentItem*> m_comments;
	QDateTime m_lastDateTime;
	Blog m_blog;
};

class CommentFilterModel : public QSortFilterProxyModel
{
	Q_OBJECT
public:
	CommentFilterModel(QObject* parent = NULL);
	~CommentFilterModel();

	static CommentsModel::CommentItem* comment(const QModelIndex& index);
	void setFilter(CommentData::CommentStatus status);
	CommentData::CommentStatus filterStatus()const{return m_status;}
	QModelIndex mapFromSource ( const QModelIndex & sourceIndex ) const;
	QModelIndex mapToSource ( const QModelIndex & proxyIndex ) const;
	bool lessThan ( const QModelIndex & left, const QModelIndex & right ) const;
	bool canFetchMore ( const QModelIndex & parent ) const;
	void fetchMore ( const QModelIndex & parent );
signals:
	void filterChanged(CommentData::CommentStatus);
protected:
	bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const;
protected:
	CommentData::CommentStatus m_status;

};
#endif